home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / amyboard / amiga / muiclass.c < prev    next >
C/C++ Source or Header  |  1995-08-12  |  40KB  |  1,413 lines

  1. /***
  2. ***  muiclass.c         -- MUI chessboard class for AmyBoard
  3. ***  Copyright(C) 1995  Free Software Foundation
  4. ***
  5. ***  ------------------------------------------------------------------------
  6. ***  This program is free software; you can redistribute it and/or modify
  7. ***  it under the terms of the GNU General Public License as published by
  8. ***  the Free Software Foundation; either version 2 of the License, or
  9. ***  (at your option) any later version.
  10. ***
  11. ***  This program is distributed in the hope that it will be useful,
  12. ***  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ***  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ***  GNU General Public License for more details.
  15. ***
  16. ***  You should have received a copy of the GNU General Public License
  17. ***  along with this program; if not, write to the Free Software
  18. ***  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19. ***  ------------------------------------------------------------------------
  20. ***
  21. ***
  22. ***  Computer: Amiga 1200
  23. ***  Compiler: Dice 3.01
  24. ***
  25. ***  Author:     Jochen Wiedmann
  26. ***              Am Eisteich 9
  27. ***              72555 Metzingen
  28. ***              Germany
  29. ***              Phone: (0049) +7123 / 14881
  30. ***              Internet: wiedmann@neckar-alb.de
  31. **/
  32. /**/
  33.  
  34.  
  35. /*** Include section
  36. **/
  37. #include "amyboard.h"
  38.  
  39. #include <exec/memory.h>
  40. #include <libraries/iffparse.h>
  41. #include <graphics/gfx.h>
  42. #include <graphics/rpattr.h>
  43. #include <proto/graphics.h>
  44.  
  45. /**/
  46.  
  47.  
  48. /*** Data section
  49. **/
  50. struct Library *MUIMasterBase       = NULL;
  51. Class *SuperClass                   = NULL;
  52. Class *ThisClass                    = NULL;
  53.  
  54. typedef struct
  55. { ULONG reqSquareWidth;
  56.   ULONG reqSquareHeight;
  57.   ULONG squareWidth;
  58.   ULONG squareHeight;
  59.   ULONG lightSquarePen;
  60.   ULONG darkSquarePen;
  61.   ULONG whitePiecePen;
  62.   ULONG blackPiecePen;
  63.   ULONG reqLightSquarePen;
  64.   ULONG reqDarkSquarePen;
  65.   ULONG reqWhitePiecePen;
  66.   ULONG reqBlackPiecePen;
  67.   LONG fromX;
  68.   LONG fromY;
  69.   LONG toX;
  70.   LONG toY;
  71.   LONG pieceX;
  72.   LONG pieceY;
  73.   UBYTE *reqPawnBitmap;
  74.   UBYTE *reqKnightBitmap;
  75.   UBYTE *reqBishopBitmap;
  76.   UBYTE *reqRookBitmap;
  77.   UBYTE *reqQueenBitmap;
  78.   UBYTE *reqKingBitmap;
  79.   UBYTE *solidPawnBitmap;
  80.   UBYTE *solidKnightBitmap;
  81.   UBYTE *solidBishopBitmap;
  82.   UBYTE *solidRookBitmap;
  83.   UBYTE *solidQueenBitmap;
  84.   UBYTE *solidKingBitmap;
  85.   APTR promotionUp;
  86.   APTR piecePopUp;
  87.   STRPTR bitmapDirectory;
  88.   Board oldBoard;
  89.   Board currentBoard;
  90.   BOOL flipView;
  91.   BOOL showCoords;
  92.   BOOL oldBoardValid;
  93.   BOOL alwaysPromoteToQueen;
  94.   BOOL editPosition;
  95.   BOOL menuDisabled;
  96. } XBoardClassData;
  97.  
  98. extern Board initialPosition;
  99. /**/
  100.  
  101.  
  102. /***  Class dispatcher
  103. **/
  104. Object *xboardmNew(Class *, Object *, struct opSet *);
  105. VOID xboardmDispose(Class *, Object *, Msg);
  106. ULONG xboardmSet(Class *, Object *obj, struct opSet *);
  107. ULONG xboardmGet(Class *, Object *obj, struct opGet *);
  108. ULONG xboardmAskMinMax(Class *, Object *, struct MUIP_AskMinMax *);
  109. ULONG xboardmDraw(Class *, Object *, struct MUIP_Draw *);
  110. ULONG xboardmDrawPosition(Class *, Object *, Msg);
  111. ULONG xboardmHandleInput(Class *, Object *, struct MUIP_HandleInput *);
  112. ULONG xboardmSetup(Class *, Object *, struct MUIP_Setup *);
  113. ULONG xboardmCleanup(Class *, Object *, Msg);
  114. _HOOK_FUNC(ULONG, XBoardClassDispatcher, Class *cl,
  115.                      Object *obj,
  116.                      Msg msg)
  117.  
  118. { switch(msg->MethodID)
  119.   { case OM_NEW:
  120.       return((ULONG) xboardmNew(cl, obj, (struct opSet *) msg));
  121.     case OM_DISPOSE:
  122.       xboardmDispose(cl, obj, msg);
  123.       return(TRUE);
  124.     case OM_SET:
  125.       return(xboardmSet(cl, obj, (struct opSet *) msg));
  126.     case OM_GET:
  127.       return(xboardmGet(cl, obj, (struct opGet *) msg));
  128.     case MUIM_AskMinMax:
  129.       return(xboardmAskMinMax(cl, obj, (struct MUIP_AskMinMax *) msg));
  130.     case MUIM_XBoard_DrawPosition:
  131.       return(xboardmDrawPosition(cl, obj, msg));
  132.     case MUIM_Draw:
  133.       return(xboardmDraw(cl, obj, (struct MUIP_Draw *) msg));
  134.     case MUIM_HandleInput:
  135.       return(xboardmHandleInput(cl, obj, (struct MUIP_HandleInput *) msg));
  136.     case MUIM_Setup:
  137.       return(xboardmSetup(cl, obj, (struct MUIP_Setup *) msg));
  138.     case MUIM_Cleanup:
  139.       return(xboardmCleanup(cl, obj, msg));
  140.   }
  141.   return(DoSuperMethodA(cl, obj, msg));
  142. }
  143. /**/
  144.  
  145.  
  146. /*** Bitmap handling functions
  147. **/
  148. VOID XBoardFreeBitmap(UBYTE *bitmap)
  149.  
  150. { FreeVec(bitmap);
  151. }
  152.  
  153. UBYTE *XBoardAllocBitmap(ULONG sizex, ULONG sizey)
  154.  
  155. { return(AllocVec(MEMF_CHIP, RASSIZE(sizex, sizey)));
  156. }
  157.  
  158. UBYTE *XBoardLoadBitmap(XBoardClassData *data, char c)
  159.  
  160. { UBYTE bitmapName[30];
  161.   UBYTE pathName[512];
  162.   BPTR file;
  163.  
  164.   sprintf((char *) bitmapName, "b%ldx%ld%c.bm",
  165.       data->reqSquareWidth, data->reqSquareHeight, c);
  166.   strcpy((char *) bitmapName, (char *) data->bitmapDirectory);
  167.   AddPart(pathName, bitmapName, sizeof(pathName));
  168.   if ((file = Open(pathName, MODE_OLDFILE)))
  169.   { UBYTE *bitmap;
  170.  
  171.     if ((bitmap = XBoardAllocBitmap(data->reqSquareWidth, data->reqSquareHeight)))
  172.     { int size = RASSIZE(data->reqSquareWidth, data->reqSquareHeight);
  173.  
  174.       if (Read(file, bitmap, size) == size)
  175.       { Close(file);
  176.     return(bitmap);
  177.       }
  178.       XBoardFreeBitmap(bitmap);
  179.     }
  180.     Close(file);
  181.   }
  182.   return(NULL);
  183. }
  184.  
  185.  
  186.  
  187.  
  188.  
  189. /**
  190. ***  Builtin bitmaps
  191. **/
  192. #define XBOARD_MAXWIDTH 80
  193. #define XBOARD_MAXHEIGHT 80
  194. #define XBOARD_MINWIDTH 44
  195. #define XBOARD_MINHEIGHT 19
  196.  
  197. typedef struct
  198. { UBYTE *bits;
  199. } builtinBitmap;
  200. struct builtinBitmapTable
  201. { builtinBitmap bitmaps[6];
  202.   int width, height;
  203. };
  204.  
  205. extern UBYTE p80s_bits[], r80s_bits[], n80s_bits[],
  206.          b80s_bits[], q80s_bits[], k80s_bits[],
  207.          p64s_bits[], r64s_bits[], n64s_bits[],
  208.          b64s_bits[], q64s_bits[], k64s_bits[],
  209.          p40s_bits[], r40s_bits[], n40s_bits[],
  210.          b40s_bits[], q40s_bits[], k40s_bits[],
  211.          p44x22s_bits[], r44x22s_bits[], n44x22s_bits[],
  212.          b44x22s_bits[], q44x22s_bits[], k44x22s_bits[],
  213.          p44x19s_bits[], r44x19s_bits[], n44x19s_bits[],
  214.          b44x19s_bits[], q44x19s_bits[], k44x19s_bits[];
  215.  
  216. const struct builtinBitmapTable XBOARD_BUILTIN_BITMAPS [] =
  217. { { { { p80s_bits }, { r80s_bits }, { n80s_bits },
  218.       { b80s_bits }, { q80s_bits }, { k80s_bits } }, 80, 80 },
  219.   { { { p64s_bits }, { r64s_bits }, { n64s_bits },
  220.       { b64s_bits }, { q64s_bits }, { k64s_bits } }, 64, 64 },
  221.   { { { p40s_bits }, { r40s_bits }, { n40s_bits },
  222.       { b40s_bits }, { q40s_bits }, { k40s_bits } }, 40, 40 },
  223.   { { { p44x22s_bits }, { r44x22s_bits }, { n44x22s_bits },
  224.       { b44x22s_bits }, { q44x22s_bits }, { k44x22s_bits } }, 44, 22 },
  225.   { { { p44x19s_bits }, { r44x19s_bits }, { n44x19s_bits },
  226.       { b44x19s_bits }, { q44x19s_bits }, { k44x19s_bits } }, 44, 19 },
  227.   { { { NULL      }, { NULL      }, { NULL      },
  228.       { NULL      }, { NULL      }, { NULL      } }, 0,  0  }
  229. };
  230.  
  231. void InitBuiltinBitmaps(void)
  232.  
  233. { /**
  234.   ***  X holds the bits of a byte in reversed order. We need to
  235.   ***  rearrange this.
  236.   **/
  237.   struct builtinBitmapTable *bbmt;
  238.  
  239.   for (bbmt = (struct builtinBitmapTable *) XBOARD_BUILTIN_BITMAPS;
  240.        bbmt->width;
  241.        bbmt++)
  242.   { int i;
  243.  
  244.     for (i = 0;  i < 6;  i++)
  245.     { UBYTE *ptr = bbmt->bitmaps[i].bits;
  246.       int j;
  247.  
  248.       for (j = RASSIZE(bbmt->width, bbmt->height);  j;  --j)
  249.       { UBYTE c;
  250.  
  251.     c = *ptr;
  252.     *ptr++ = ((c & 0x80) >> 7) |
  253.          ((c & 0x40) >> 5) |
  254.          ((c & 0x20) >> 3) |
  255.          ((c & 0x10) >> 1) |
  256.          ((c & 0x08) << 1) |
  257.          ((c & 0x04) << 3) |
  258.          ((c & 0x02) << 5) |
  259.          ((c & 0x01) << 7);
  260.       }
  261.     }
  262.   }
  263. }
  264.  
  265. struct builtinBitmapTable *XBoardAskBuiltinBitmap(ULONG width, ULONG height)
  266.  
  267. { struct builtinBitmapTable *bbmt;
  268.  
  269.   for (bbmt = (struct builtinBitmapTable *) XBOARD_BUILTIN_BITMAPS;
  270.        bbmt->width;
  271.        bbmt++)
  272.   { if ((bbmt->width << 3) <= width  &&
  273.     (bbmt->height << 3) <= height)
  274.     { return(bbmt);
  275.     }
  276.   }
  277.   return(NULL);
  278. }
  279. UBYTE *XBoardGetBuiltinBitmap(struct builtinBitmapTable *bbmt, char piece)
  280.  
  281. { builtinBitmap *bitmaps = bbmt->bitmaps;
  282.  
  283.   switch (piece)
  284.   { case 'p':
  285.       return(bitmaps[0].bits);
  286.     case 'r':
  287.       return(bitmaps[1].bits);
  288.     case 'n':
  289.       return(bitmaps[2].bits);
  290.     case 'b':
  291.       return(bitmaps[3].bits);
  292.     case 'q':
  293.       return(bitmaps[4].bits);
  294.     case 'k':
  295.       return(bitmaps[5].bits);
  296.   }
  297.   return(NULL);
  298. }
  299. /**/
  300.  
  301.  
  302. /****** XBoard.mcc/MUIA_XBoard_SquareWidth *********************************
  303. *
  304. *   NAME
  305. *       MUIA_XBoard_SquareWidth - set square width [I.G], ULONG
  306. *
  307. *   FUNCTION
  308. *       This attribute determines the width of one chessboard square.
  309. *       The chessboards width will be the square width multiplied by
  310. *       8, the number of squares.
  311. *
  312. *       If you don't set this attribute, the chessboard gadget will
  313. *       use reasonable defaults. Otherwise you should additionally set
  314. *       the attributes MUIA_XBoard_SquareHeight and
  315. *       MUIA_XBoard_BitmapDirectory too, because in that case the
  316. *       bitmaps are loaded from the disk.
  317. *
  318. *       Note, that these settings can be overwritten, if the window
  319. *       gets resized too small.
  320. *
  321. *   SEE ALSO
  322. *       MUIA_XBoard_SquareHeight, MUIA_XBoard_BitmapDirectory
  323. *
  324. ***************************************************************************/
  325. /**/
  326. /****** XBoard.mcc/MUIA_XBoard_SquareHeight ********************************
  327. *
  328. *   NAME
  329. *       MUIA_XBoard_SquareHeight - set square height [I.G], ULONG
  330. *
  331. *   FUNCTION
  332. *       This attribute determines the height of one chessboard square.
  333. *       The chessboards height will be the square height multiplied by
  334. *       8, the number of squares.
  335. *
  336. *       If you don't set this attribute, the chessboard gadget will
  337. *       use reasonable defaults. Otherwise you should additionally set
  338. *       the attributes MUIA_XBoard_SquareWidth and
  339. *       MUIA_XBoard_BitmapDirectory too, because in that case the
  340. *       bitmaps are loaded from the disk.
  341. *
  342. *       Note, that these settings can be overwritten, if the window
  343. *       gets resized too small.
  344. *
  345. *   SEE ALSO
  346. *       MUIA_XBoard_SquareWidth, MUIA_XBoard_BitmapDirectory
  347. *
  348. ***************************************************************************/
  349. /**/
  350. /****** XBoard.mcc/MUIA_XBoard_BitmapDirectory *****************************
  351. *
  352. *   NAME
  353. *       MUIA_BitmapDirectory - set bitmap directory [I..], STRPTR
  354. *
  355. *   FUNCTION
  356. *       By setting this attribute you can use your own bitmaps
  357. *       for the chessboard gadget. These bitmaps must be stored
  358. *       as separate files called "xns.bm", where x means
  359. *           p   pawn
  360. *           r   rook
  361. *           n   knight
  362. *           b   bishop
  363. *           q   queen
  364. *           k   king
  365. *       and n is the square size as supplied with
  366. *       MUIA_XBoard_SquareSize. Thus a filename like "q64s.bm"
  367. *       means "Queen, square size 64 pixels".
  368. *
  369. *       Actually the only supported format is X11 bitmap format.
  370. *
  371. *   BUGS
  372. *       The string will not be copied and has to remain valid as
  373. *       long as the object lives.
  374. *
  375. *   SEE ALSO
  376. *       MUIA_XBoard_SquareSize
  377. *
  378. ***************************************************************************/
  379. /**/
  380. /****** XBoard.mcc/MUIA_XBoard_FlipView ************************************
  381. *
  382. *   NAME
  383. *       MUIA_XBoard_Flipview - set chessboard direction [ISG], BOOL
  384. *
  385. *   FUNCTION
  386. *       Usually the chessboard displays the white pieces at the
  387. *       bottom moving to the top of the board. By setting this
  388. *       attribute to TRUE (typically, if the user has the black
  389. *       pieces), you get the white pieces at the top of the
  390. *       chessboard.
  391. *
  392. ***************************************************************************/
  393. /**/
  394. /****** XBoard.mcc/MUIA_XBoard_ShowCoords **********************************
  395. *
  396. *   NAME
  397. *       MUIA_XBoard_ShowCoords - show square coordinates [ISG], BOOL
  398. *
  399. *   FUNCTION
  400. *       This attribute displays coordinates at the bottom and the
  401. *       right side of the chessboard, respectively.
  402. *
  403. ***************************************************************************/
  404. /**/
  405. /****** XBoard.mcc/MUIA_XBoard_LightSquarePen ******************************
  406. *
  407. *   NAME
  408. *       MUIA_XBoard_LightSquarePen - white squares pen [I.G], ULONG
  409. *
  410. *   FUNCTION
  411. *       Pen of the light squares on the chessboard
  412. *
  413. *   SEE ALSO
  414. *       MUIA_XBoard_DarkSquarePen, MUIA_XBoard_WhitePiecePen,
  415. *       MUIA_XBoard_BlackPiecePen
  416. *
  417. ***************************************************************************/
  418. /**/
  419. /****** XBoard.mcc/MUIA_XBoard_DarkSquarePen *******************************
  420. *
  421. *   NAME
  422. *       MUIA_XBoard_DarkSquarePen - black squares pen [I.G], ULONG
  423. *
  424. *   FUNCTION
  425. *       Pen of the dark squares on the chessboard
  426. *
  427. *   SEE ALSO
  428. *       MUIA_XBoard_LightSquarePen, MUIA_XBoard_WhitePiecePen,
  429. *       MUIA_XBoard_BlackPiecePen
  430. *
  431. ***************************************************************************/
  432. /**/
  433. /****** XBoard.mcc/MUIA_XBoard_WhitePiecePen *******************************
  434. *
  435. *   NAME
  436. *       MUIA_XBoard_WhitePiecePen - white pieces pen [I.G], ULONG
  437. *
  438. *   FUNCTION
  439. *       Pen of the white squares on the chessboard
  440. *
  441. *   SEE ALSO
  442. *       MUIA_XBoard_LightSquarePen, MUIA_XBoard_DarkSquarePen,
  443. *       MUIA_XBoard_BlackPiecePen
  444. *
  445. ***************************************************************************/
  446. /**/
  447. /****** XBoard.mcc/MUIA_XBoard_BlackPiecePen *******************************
  448. *
  449. *   NAME
  450. *       MUIA_XBoard_BlackPiecePen - black pieces pen [I.G], ULONG
  451. *
  452. *   FUNCTION
  453. *       Pen of the black pieces on the chessboard
  454. *
  455. *   SEE ALSO
  456. *       MUIA_XBoard_LightSquarePen, MUIA_XBoard_DarkSquarePen,
  457. *       MUIA_XBoard_WhitePiecePen
  458. *
  459. ***************************************************************************/
  460. /**/
  461. /***** XBoard.mcc/MUIA_XBoard_AlwaysPromoteToQueen *************************
  462. *
  463. *   NAME
  464. *       MUIA_XBoard_AlwaysPromoteToQueen - force queen
  465. *                                       promotion [ISG], ULONG
  466. *
  467. *   FUNCTION
  468. *       Setting this attribute to TRUE disables the promotion
  469. *       requester. Pawns will always be promoted to queens
  470. *       instead.
  471. *
  472. ***************************************************************************/
  473. /**/
  474. /***** XBoard.mcc/MUIA_XBoard_EditPosition *********************************
  475. *
  476. *   NAME
  477. *       MUIA_XBoard_EditPosition - edit a position [ISG], ULONG
  478. *
  479. *   FUNCTION
  480. *       If this attribute is TRUE, user inputs will be handled
  481. *       differently: A mouseclick on a square will popup a
  482. *       requester, that allows the user to select a piece which
  483. *       will be placed on that square.
  484. *
  485. ***************************************************************************/
  486. /**/
  487.  
  488.  
  489. /*** OM_New method
  490. **/
  491. Object *xboardmNew(Class *cl, Object *obj, struct opSet *msg)
  492.  
  493. { Object *newobj;
  494.   XBoardClassData *data;
  495.  
  496.   if (!(newobj = (Object *) DoSuperMethodA(cl, obj, (Msg) msg)))
  497.   { return(NULL);
  498.   }
  499.  
  500.   data = INST_DATA(cl, newobj);
  501.  
  502.   data->reqSquareWidth = 0;
  503.   data->reqSquareHeight = 0;
  504.   data->squareWidth = 0;
  505.   data->squareHeight = 0;
  506.   data->reqPawnBitmap = NULL;
  507.   data->reqRookBitmap = NULL;
  508.   data->reqKnightBitmap = NULL;
  509.   data->reqBishopBitmap = NULL;
  510.   data->reqQueenBitmap = NULL;
  511.   data->reqKingBitmap = NULL;
  512.   data->solidPawnBitmap = NULL;
  513.   data->solidRookBitmap = NULL;
  514.   data->solidKnightBitmap = NULL;
  515.   data->solidBishopBitmap = NULL;
  516.   data->solidQueenBitmap = NULL;
  517.   data->solidKingBitmap = NULL;
  518.   data->bitmapDirectory = NULL;
  519.   data->flipView = FALSE;
  520.   data->showCoords = FALSE;
  521.   data->oldBoardValid = FALSE;
  522.   data->lightSquarePen = -1;
  523.   data->darkSquarePen = -1;
  524.   data->whitePiecePen = -1;
  525.   data->blackPiecePen = -1;
  526.   data->reqLightSquarePen = -1;
  527.   data->reqDarkSquarePen = -1;
  528.   data->reqWhitePiecePen = -1;
  529.   data->reqBlackPiecePen = -1;
  530.   data->fromX = -1;
  531.   data->fromY = -1;
  532.   data->toX = -1;
  533.   data->toY = -1;
  534.   data->promotionUp = NULL;
  535.   data->alwaysPromoteToQueen = FALSE;
  536.   data->editPosition = FALSE;
  537.   data->piecePopUp = NULL;
  538.   CopyMem(&initialPosition, &data->currentBoard, sizeof(Board));
  539.  
  540.   set(newobj, MUIA_Font, MUIV_Font_Tiny);
  541.   DoMethod(newobj, OM_SET, msg->ops_AttrList);
  542.  
  543.   /**
  544.   ***  Try to load the requested bitmaps from disk.
  545.   **/
  546.   if (data->bitmapDirectory  &&
  547.       data->reqSquareWidth  &&
  548.       data->reqSquareHeight)
  549.   { if (!(data->reqPawnBitmap = XBoardLoadBitmap(data, 'p'))    ||
  550.     !(data->reqRookBitmap = XBoardLoadBitmap(data, 'r'))    ||
  551.     !(data->reqKnightBitmap = XBoardLoadBitmap(data, 'n'))  ||
  552.     !(data->reqBishopBitmap = XBoardLoadBitmap(data, 'b'))  ||
  553.     !(data->reqQueenBitmap = XBoardLoadBitmap(data, 'q'))   ||
  554.     !(data->reqKingBitmap = XBoardLoadBitmap(data, 'k')))
  555.     { XBoardFreeBitmap(data->reqPawnBitmap);
  556.       XBoardFreeBitmap(data->reqRookBitmap);
  557.       XBoardFreeBitmap(data->reqKnightBitmap);
  558.       XBoardFreeBitmap(data->reqBishopBitmap);
  559.       XBoardFreeBitmap(data->reqKingBitmap);
  560.       XBoardFreeBitmap(data->reqQueenBitmap);
  561.       data->reqPawnBitmap = NULL;
  562.       data->reqRookBitmap = NULL;
  563.       data->reqKnightBitmap = NULL;
  564.       data->reqBishopBitmap = NULL;
  565.       data->reqKingBitmap = NULL;
  566.       data->reqQueenBitmap = NULL;
  567.     }
  568.   }
  569.  
  570.   return(newobj);
  571. }
  572. /**/
  573.  
  574.  
  575. /*** CloseMuiWindow() function
  576. **/
  577. _HOOK_FUNC(void, windowCloseCallback, struct Hook *hook,
  578.                       Object *app,
  579.                       va_list args)
  580. { Object *window;
  581.  
  582.   window = va_arg(args, Object *);
  583.   DoMethod(app, OM_REMMEMBER, window);
  584.   MUI_DisposeObject(window);
  585. }
  586. struct Hook windowCloseCallbackHook =
  587. { { NULL, NULL },
  588.   (HOOKFUNC) windowCloseCallback,
  589.   NULL,
  590.   NULL
  591. };
  592.  
  593.    
  594. VOID CloseMuiWindow(Object *win)
  595.  
  596. { set(win, MUIA_Window_Open, FALSE);
  597.   DoMethod(_app(win), MUIM_Application_PushMethod,
  598.        _app(win), 3, MUIM_CallHook, &windowCloseCallbackHook, win);
  599. }
  600. /**/
  601.  
  602.  
  603. /*** OM_Dispose method
  604. **/
  605. VOID PromotionPopDown(Class *cl, Object *obj)
  606.  
  607. { XBoardClassData *data = INST_DATA(cl, obj);
  608.  
  609.   if (data->promotionUp)
  610.   { CloseMuiWindow(data->promotionUp);
  611.     data->promotionUp = NULL;
  612.   }
  613.   data->fromX = -1;
  614.   data->fromY = -1;
  615.   data->toX = -1;
  616.   data->toY = -1;
  617. }
  618.  
  619. VOID PiecePopDown(Class *cl, Object *obj)
  620.  
  621. { XBoardClassData *data = INST_DATA(cl, obj);
  622.  
  623.   if (data->piecePopUp)
  624.   { CloseMuiWindow(data->piecePopUp);
  625.     data->piecePopUp = NULL;
  626.   }
  627.   data->fromX = -1;
  628.   data->fromY = -1;
  629. }
  630.  
  631. VOID xboardmDispose(Class *cl, Object *obj, Msg msg)
  632.  
  633. { XBoardClassData *data = INST_DATA(cl, obj);
  634.  
  635.   PromotionPopDown(cl, obj);
  636.   PiecePopDown(cl, obj);
  637.  
  638.   XBoardFreeBitmap(data->reqPawnBitmap);
  639.   XBoardFreeBitmap(data->reqRookBitmap);
  640.   XBoardFreeBitmap(data->reqKnightBitmap);
  641.   XBoardFreeBitmap(data->reqBishopBitmap);
  642.   XBoardFreeBitmap(data->reqQueenBitmap);
  643.   XBoardFreeBitmap(data->reqKingBitmap);
  644.   DoSuperMethodA(cl, obj, msg);
  645. }
  646. /**/
  647.  
  648.  
  649. /*** OM_Set method
  650. **/
  651. ULONG xboardmSet(Class *cl, Object *obj, struct opSet *msg)
  652.  
  653. { XBoardClassData *data = INST_DATA(cl, obj);
  654.   struct TagItem *tiptr, *ti;
  655.  
  656.   tiptr = msg->ops_AttrList;
  657.   while((ti = NextTagItem(&tiptr)))
  658.   { switch(ti->ti_Tag)
  659.     { case MUIA_XBoard_SquareWidth:
  660.     data->reqSquareWidth = ti->ti_Data;
  661.     break;
  662.       case MUIA_XBoard_SquareHeight:
  663.     data->reqSquareHeight = ti->ti_Data;
  664.     break;
  665.       case MUIA_XBoard_BitmapDirectory:
  666.     data->bitmapDirectory = (STRPTR) ti->ti_Data;
  667.     break;
  668.       case MUIA_XBoard_FlipView:
  669.     { BOOL oldflipView = data->flipView;
  670.  
  671.       data->flipView = (BOOL) ti->ti_Data;
  672.       if (data->flipView != oldflipView)
  673.       { MUI_Redraw(obj, MADF_DRAWOBJECT);
  674.       }
  675.     }
  676.     break;
  677.       case MUIA_XBoard_ShowCoords:
  678.     { BOOL oldShowCoords = data->showCoords;
  679.  
  680.       data->showCoords = (BOOL) ti->ti_Data;
  681.       if (data->showCoords != oldShowCoords)
  682.       { MUI_Redraw(obj, MADF_DRAWOBJECT);
  683.       }
  684.     }
  685.     break;
  686.       case MUIA_XBoard_LightSquarePen:
  687.     data->reqLightSquarePen = ti->ti_Data;
  688.     break;
  689.       case MUIA_XBoard_DarkSquarePen:
  690.     data->reqDarkSquarePen = ti->ti_Data;
  691.     break;
  692.       case MUIA_XBoard_WhitePiecePen:
  693.     data->reqWhitePiecePen = ti->ti_Data;
  694.     break;
  695.       case MUIA_XBoard_BlackPiecePen:
  696.     data->reqBlackPiecePen = ti->ti_Data;
  697.     break;
  698.       case MUIA_XBoard_AlwaysPromoteToQueen:
  699.     data->alwaysPromoteToQueen = ti->ti_Data;
  700.     break;
  701.       case MUIA_XBoard_EditPosition:
  702.     data->editPosition = ti->ti_Data;
  703.     break;
  704.     }
  705.   }
  706.   return(DoSuperMethodA(cl, obj, (Msg) msg));
  707. }
  708. /**/
  709.  
  710.  
  711. /*** OM_Get method
  712. **/
  713. ULONG xboardmGet(Class *cl, Object *obj, struct opGet *msg)
  714.  
  715. { XBoardClassData *data = INST_DATA(cl, obj);
  716.   ULONG *store = msg->opg_Storage;
  717.  
  718.   switch (msg->opg_AttrID)
  719.   { case MUIA_XBoard_SquareWidth:
  720.       *store = data->squareWidth;
  721.       break;
  722.     case MUIA_XBoard_SquareHeight:
  723.       *store = data->squareHeight;
  724.       break;
  725.     case MUIA_XBoard_BitmapDirectory:
  726.       *store = (ULONG) data->bitmapDirectory;
  727.       break;
  728.     case MUIA_XBoard_FlipView:
  729.       *store = (ULONG) data->flipView;
  730.       break;
  731.     case MUIA_XBoard_ShowCoords:
  732.       *store = (ULONG) data->showCoords;
  733.       break;
  734.     case MUIA_XBoard_LightSquarePen:
  735.       *store = data->reqLightSquarePen;
  736.       break;
  737.     case MUIA_XBoard_DarkSquarePen:
  738.       *store = data->reqDarkSquarePen;
  739.       break;
  740.     case MUIA_XBoard_WhitePiecePen:
  741.       *store = data->reqWhitePiecePen;
  742.       break;
  743.     case MUIA_XBoard_BlackPiecePen:
  744.       *store = data->reqBlackPiecePen;
  745.       break;
  746.     case MUIA_XBoard_AlwaysPromoteToQueen:
  747.       *store = data->alwaysPromoteToQueen;
  748.       break;
  749.     case MUIA_XBoard_EditPosition:
  750.       *store = data->editPosition;
  751.       break;
  752.     default:
  753.       return(DoSuperMethodA(cl, obj, (Msg) msg));
  754.   }
  755.   return(TRUE);
  756. }
  757. /**/
  758.  
  759.  
  760. /*** MUIM_AskMinMax method
  761. **/
  762. ULONG xboardmAskMinMax(Class *cl, Object *obj, struct MUIP_AskMinMax *msg)
  763.  
  764. { XBoardClassData *data = INST_DATA(cl, obj);
  765.  
  766.   DoSuperMethodA(cl, obj, (Msg) msg);
  767.  
  768.   if (!data->reqPawnBitmap)
  769.   { data->reqSquareWidth = XBOARD_MAXWIDTH;
  770.     data->reqSquareHeight = XBOARD_MAXHEIGHT;
  771.   }
  772.   msg->MinMaxInfo->MinWidth += MIN(XBOARD_MINWIDTH, data->reqSquareWidth) << 3;
  773.   msg->MinMaxInfo->MinHeight += MIN(XBOARD_MINHEIGHT, data->reqSquareHeight) << 3;
  774.   msg->MinMaxInfo->DefWidth += data->reqSquareWidth << 3;
  775.   msg->MinMaxInfo->DefHeight += data->reqSquareHeight << 3;
  776.   msg->MinMaxInfo->MaxWidth += data->reqSquareWidth << 3;
  777.   msg->MinMaxInfo->MaxHeight += data->reqSquareHeight << 3;
  778.   return(0);
  779. }
  780. /**/
  781.  
  782.  
  783. /*** XBoardDrawSquare() function
  784. **/
  785. VOID XBoardDrawSquare(Object *obj, XBoardClassData *data, int i, int j,
  786.               ChessSquare cs, struct RastPort *rp)
  787.  
  788. { ULONG left = _left(obj);
  789.   ULONG top = _top(obj);
  790.   ULONG width = _width(obj);
  791.   ULONG height = _height(obj);
  792.   ULONG sizex = data->squareWidth;
  793.   ULONG sizey = data->squareHeight;
  794.   BOOL whiteSquare = ((i + j) % 2) != 0;
  795.   ULONG colorA, colorB;
  796.   UBYTE *bitmap;
  797.   int cI, cJ;
  798.  
  799.   cI = i;
  800.   cJ = j;
  801.   if (data->flipView)
  802.   { i = 7-i;
  803.     j = 7-j;
  804.   }
  805.  
  806.   left += ((width - (sizex << 3)) >> 2) + j * sizex;
  807.   top += ((height - (sizey << 3)) >> 2) + (7-i) * sizey;
  808.  
  809.   colorB = whiteSquare ? data->lightSquarePen : data->darkSquarePen;
  810.   colorA = colorB;  /*  Suppress warnings on uninitialized variables */
  811.   bitmap = data->solidPawnBitmap;
  812.  
  813.   switch(cs)
  814.   { case WhitePawn:
  815.       colorA = data->whitePiecePen;
  816.       bitmap = data->solidPawnBitmap;
  817.       break;
  818.     case WhiteRook:
  819.       colorA = data->whitePiecePen;
  820.       bitmap = data->solidRookBitmap;
  821.       break;
  822.     case WhiteKnight:
  823.       colorA = data->whitePiecePen;
  824.       bitmap = data->solidKnightBitmap;
  825.       break;
  826.     case WhiteBishop:
  827.       colorA = data->whitePiecePen;
  828.       bitmap = data->solidBishopBitmap;
  829.       break;
  830.     case WhiteQueen:
  831.       colorA = data->whitePiecePen;
  832.       bitmap = data->solidQueenBitmap;
  833.       break;
  834.     case WhiteKing:
  835.       colorA = data->whitePiecePen;
  836.       bitmap = data->solidKingBitmap;
  837.       break;
  838.     case BlackPawn:
  839.       colorA = data->blackPiecePen;
  840.       bitmap = data->solidPawnBitmap;
  841.       break;
  842.     case BlackRook:
  843.       colorA = data->blackPiecePen;
  844.       bitmap = data->solidRookBitmap;
  845.       break;
  846.     case BlackKnight:
  847.       colorA = data->blackPiecePen;
  848.       bitmap = data->solidKnightBitmap;
  849.       break;
  850.     case BlackBishop:
  851.       colorA = data->blackPiecePen;
  852.       bitmap = data->solidBishopBitmap;
  853.       break;
  854.     case BlackQueen:
  855.       colorA = data->blackPiecePen;
  856.       bitmap = data->solidQueenBitmap;
  857.       break;
  858.     case BlackKing:
  859.       colorA = data->blackPiecePen;
  860.       bitmap = data->solidKingBitmap;
  861.       break;
  862.     default:
  863.       break;
  864.   }
  865.  
  866.   SetABPenDrMd(rp, colorA, colorB, JAM2);
  867.   BltTemplate(bitmap, 0, ((data->squareWidth+15)>>3)&0xFFFE, rp, left, top, sizex, sizey);
  868.  
  869.   if (data->showCoords)
  870.   { char coords[3];
  871.     struct TextExtent te;
  872.  
  873.     coords[0] = 'A'+cJ;
  874.     coords[1] = '1'+cI;
  875.     coords[2] = '\0';
  876.  
  877.     SetABPenDrMd(rp, whiteSquare ? data->darkSquarePen : data->lightSquarePen,
  878.          colorB, JAM1);
  879.     TextExtent(rp, (STRPTR) coords, 2, &te);
  880.     Move(rp, left + sizex - te.te_Width - 1, top + sizey - te.te_Height);
  881.     Text(rp, (STRPTR) coords, 2);
  882.   }
  883. }
  884. /**/
  885.  
  886.  
  887. /*** MUIM_Draw method
  888. **/
  889. ULONG xboardmDraw(Class *cl, Object *obj, struct MUIP_Draw *msg)
  890.  
  891. { XBoardClassData *data = INST_DATA(cl, obj);
  892.   ULONG width = _width(obj);
  893.   ULONG height = _height(obj);
  894.   struct RastPort *rp = _rp(obj);
  895.   struct TextFont *tf;
  896.   ULONG drMd, aPen, bPen;
  897.  
  898.   DoSuperMethodA(cl, obj, (Msg) msg);
  899.  
  900.   if (((struct Library *) GfxBase)->lib_Version >= 39)
  901.   { GetRPAttrs(rp, RPTAG_Font, &tf,
  902.            RPTAG_DrMd, &drMd,
  903.            RPTAG_APen, &aPen,
  904.            RPTAG_BPen, &bPen,
  905.            TAG_DONE);
  906.   }
  907.   else
  908.   { tf = rp->Font;
  909.     drMd = rp->DrawMode;
  910.     aPen = rp->FgPen;
  911.     bPen = rp->BgPen;
  912.   }
  913.   SetFont(rp, _font(obj));
  914.  
  915.   if (!(msg->flags & MADF_DRAWUPDATE))
  916.   { int i,j;
  917.  
  918.     if (data->reqPawnBitmap  &&
  919.     (width >= data->reqSquareWidth << 3)  &&
  920.     (height >= data->reqSquareHeight << 3))
  921.     { data->solidPawnBitmap = data->reqPawnBitmap;
  922.       data->solidRookBitmap = data->reqRookBitmap;
  923.       data->solidKnightBitmap = data->reqKnightBitmap;
  924.       data->solidBishopBitmap = data->reqBishopBitmap;
  925.       data->solidQueenBitmap = data->reqQueenBitmap;
  926.       data->solidKingBitmap = data->reqKingBitmap;
  927.       data->squareWidth = data->reqSquareWidth;
  928.       data->squareHeight = data->reqSquareHeight;
  929.     }
  930.     else
  931.     { struct builtinBitmapTable *bbmt = XBoardAskBuiltinBitmap(width, height);
  932.       data->solidPawnBitmap = XBoardGetBuiltinBitmap(bbmt, 'p');
  933.       data->solidRookBitmap = XBoardGetBuiltinBitmap(bbmt, 'r');
  934.       data->solidKnightBitmap = XBoardGetBuiltinBitmap(bbmt, 'n');
  935.       data->solidBishopBitmap = XBoardGetBuiltinBitmap(bbmt, 'b');
  936.       data->solidQueenBitmap = XBoardGetBuiltinBitmap(bbmt, 'q');
  937.       data->solidKingBitmap = XBoardGetBuiltinBitmap(bbmt, 'k');
  938.       data->squareWidth = bbmt->width;
  939.       data->squareHeight = bbmt->height;
  940.     }
  941.  
  942.     for (i = BOARD_SIZE-1;  i >= 0;  i--)
  943.     { for (j = BOARD_SIZE-1;  j >= 0;  j--)
  944.       { XBoardDrawSquare(obj, data, i, j, data->currentBoard[i][j], rp);
  945.       }
  946.     }
  947.   }
  948.   else
  949.   { int i, j;
  950.  
  951.     for (i = BOARD_SIZE-1;  i >= 0;  i--)
  952.     { for (j = BOARD_SIZE-1;  j >= 0;  j--)
  953.       { ChessSquare cs = data->currentBoard[i][j];
  954.  
  955.     if (data->oldBoard[i][j] != cs)
  956.     { XBoardDrawSquare(obj, data, i, j, cs, rp);
  957.     }
  958.       }
  959.     }
  960.   }
  961.  
  962.   CopyMem(data->currentBoard, data->oldBoard, sizeof(Board));
  963.   data->oldBoardValid = TRUE;
  964.  
  965.   if (((struct Library *) GfxBase)->lib_Version >= 39)
  966.   { SetRPAttrs(rp, RPTAG_Font, tf,
  967.            RPTAG_DrMd, drMd,
  968.            RPTAG_APen, aPen,
  969.            RPTAG_BPen, bPen,
  970.            TAG_DONE);
  971.   }
  972.   else
  973.   { SetFont(rp, tf);
  974.     SetABPenDrMd(rp, aPen, bPen, drMd);
  975.   }   
  976.  
  977.   return(0);
  978. }
  979. /**/
  980.  
  981.  
  982. /*** Chessboard editing functions
  983. **/
  984. _HOOK_FUNC(ULONG, pieceCallback, struct Hook *hook,
  985.                  Object *obj,
  986.                  va_list args)
  987.  
  988. { ChessSquare selection;
  989.   XBoardClassData *data;
  990.   LONG pieceX, pieceY;
  991.  
  992.   selection = va_arg(args, int);
  993.   data = INST_DATA(ThisClass, obj);
  994.  
  995.   pieceX = data->pieceX;
  996.   pieceY = data->pieceY;
  997.   data->pieceX = -1;
  998.   data->pieceY = -1;
  999.   if (pieceX >= 0  &&  pieceX <= 7  &&  pieceY >= 0  &&  pieceY <= 7  &&
  1000.       selection != (ChessSquare) -1)
  1001.   { EditPositionMenuEvent(selection, pieceX, pieceY);
  1002.   }
  1003.   PiecePopDown(ThisClass, obj);
  1004.   return(0);
  1005. }
  1006.  
  1007. const struct Hook pieceCallbackHook =
  1008. { { NULL, NULL },
  1009.   (HOOKFUNC) pieceCallback,
  1010.   NULL,
  1011.   NULL
  1012. };
  1013.  
  1014. VOID PiecePopUp(Class *cl, Object *obj)
  1015.  
  1016. { XBoardClassData *data = INST_DATA(cl, obj);
  1017.   APTR win, whiteKing, blackKing, whiteQueen, blackQueen,
  1018.        whiteBishop, blackBishop, whiteKnight, blackKnight,
  1019.        whiteRook, blackRook, whitePawn, blackPawn,
  1020.        emptySquare, clearBoard, whiteToPlay, blackToPlay;
  1021.   extern struct Library *MUIMasterBase;
  1022.  
  1023.   data->pieceX = data->fromX;
  1024.   data->pieceY = data->fromY;
  1025.   PiecePopDown(cl, obj);
  1026.  
  1027.   win = WindowObject,
  1028.         MUIA_Window_ID, MAKE_ID('P','I','E','C'),
  1029.         MUIA_Window_Title, "Piece requester",
  1030.         WindowContents, VGroup,
  1031.         Child, ColGroup(2),
  1032.             Child, whiteKing = MUI_MakeObject(MUIO_Button, "White King"),
  1033.             Child, blackKing = MUI_MakeObject(MUIO_Button, "Black King"),
  1034.             Child, whiteQueen = MUI_MakeObject(MUIO_Button, "White Queen"),
  1035.             Child, blackQueen = MUI_MakeObject(MUIO_Button, "Black Queen"),
  1036.             Child, whiteBishop = MUI_MakeObject(MUIO_Button, "White Bishop"),
  1037.             Child, blackBishop = MUI_MakeObject(MUIO_Button, "Black Bishop"),
  1038.             Child, whiteKnight = MUI_MakeObject(MUIO_Button, "White Knight"),
  1039.             Child, blackKnight = MUI_MakeObject(MUIO_Button, "Black Knight"),
  1040.             Child, whiteRook = MUI_MakeObject(MUIO_Button, "White Rook"),
  1041.             Child, blackRook = MUI_MakeObject(MUIO_Button, "Black Rook"),
  1042.             Child, whitePawn = MUI_MakeObject(MUIO_Button, "White Pawn"),
  1043.             Child, blackPawn = MUI_MakeObject(MUIO_Button, "Black Pawn"),
  1044.         End,
  1045.         Child, MUI_MakeObject(MUIO_HBar, 0),
  1046.         Child, ColGroup(2),
  1047.             Child, emptySquare = MUI_MakeObject(MUIO_Button, "Empty Square"),
  1048.             Child, clearBoard = MUI_MakeObject(MUIO_Button, "Clear Borard"),
  1049.         End,
  1050.         Child, MUI_MakeObject(MUIO_HBar, 0),
  1051.         Child, ColGroup(2),
  1052.             Child, whiteToPlay = MUI_MakeObject(MUIO_Button, "White to play"),
  1053.             Child, blackToPlay = MUI_MakeObject(MUIO_Button, "Black to play"),
  1054.         End,
  1055.         End,
  1056.     End;
  1057.  
  1058.   if (win)
  1059.   { ULONG open;
  1060.     APTR app = _app(obj);
  1061.  
  1062.     DoMethod(app, OM_ADDMEMBER, win);
  1063.     set(win, MUIA_Window_Open, TRUE);
  1064.     get(win, MUIA_Window_Open, &open);
  1065.  
  1066.     if (open)
  1067.     { DoMethod(win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  1068.            obj, 3, MUIM_CallHook, &pieceCallbackHook, -1);
  1069.       DoMethod(emptySquare, MUIM_Notify, MUIA_Pressed, FALSE,
  1070.            obj, 3, MUIM_CallHook, &pieceCallbackHook, EmptySquare);
  1071.       DoMethod(clearBoard, MUIM_Notify, MUIA_Pressed, FALSE,
  1072.            obj, 3, MUIM_CallHook, &pieceCallbackHook, ClearBoard);
  1073.  
  1074.       DoMethod(whiteKing, MUIM_Notify, MUIA_Pressed, FALSE,
  1075.            obj, 3, MUIM_CallHook, &pieceCallbackHook, WhiteKing);
  1076.       DoMethod(whiteQueen, MUIM_Notify, MUIA_Pressed, FALSE,
  1077.            obj, 3, MUIM_CallHook, &pieceCallbackHook, WhiteQueen);
  1078.       DoMethod(whiteBishop, MUIM_Notify, MUIA_Pressed, FALSE,
  1079.            obj, 3, MUIM_CallHook, &pieceCallbackHook, WhiteBishop);
  1080.       DoMethod(whiteKnight, MUIM_Notify, MUIA_Pressed, FALSE,
  1081.            obj, 3, MUIM_CallHook, &pieceCallbackHook, WhiteKnight);
  1082.       DoMethod(whiteRook, MUIM_Notify, MUIA_Pressed, FALSE,
  1083.            obj, 3, MUIM_CallHook, &pieceCallbackHook, WhiteRook);
  1084.       DoMethod(whitePawn, MUIM_Notify, MUIA_Pressed, FALSE,
  1085.            obj, 3, MUIM_CallHook, &pieceCallbackHook, WhitePawn);
  1086.       DoMethod(whiteToPlay, MUIM_Notify, MUIA_Pressed, FALSE,
  1087.            obj, 3, MUIM_CallHook, &pieceCallbackHook, WhitePlay);
  1088.       DoMethod(blackKing, MUIM_Notify, MUIA_Pressed, FALSE,
  1089.            obj, 3, MUIM_CallHook, &pieceCallbackHook, BlackKing);
  1090.       DoMethod(blackQueen, MUIM_Notify, MUIA_Pressed, FALSE,
  1091.            obj, 3, MUIM_CallHook, &pieceCallbackHook, BlackQueen);
  1092.       DoMethod(blackBishop, MUIM_Notify, MUIA_Pressed, FALSE,
  1093.            obj, 3, MUIM_CallHook, &pieceCallbackHook, BlackBishop);
  1094.       DoMethod(blackKnight, MUIM_Notify, MUIA_Pressed, FALSE,
  1095.            obj, 3, MUIM_CallHook, &pieceCallbackHook, BlackKnight);
  1096.       DoMethod(blackRook, MUIM_Notify, MUIA_Pressed, FALSE,
  1097.            obj, 3, MUIM_CallHook, &pieceCallbackHook, BlackRook);
  1098.       DoMethod(blackPawn, MUIM_Notify, MUIA_Pressed, FALSE,
  1099.            obj, 3, MUIM_CallHook, &pieceCallbackHook, BlackPawn);
  1100.       DoMethod(blackToPlay, MUIM_Notify, MUIA_Pressed, FALSE,
  1101.            obj, 3, MUIM_CallHook, &pieceCallbackHook, BlackPlay);
  1102.  
  1103.       data->piecePopUp = win;
  1104.  
  1105.       return;
  1106.     }
  1107.     else
  1108.     { DoMethod(_app(obj), OM_REMMEMBER, win);
  1109.       MUI_DisposeObject(win);
  1110.     }
  1111.   }
  1112.  
  1113.   DisplayFatalError("Out of memory", 0, 10);
  1114. }
  1115. /**/
  1116.  
  1117.  
  1118. /*** Promotion functions
  1119. **/
  1120. _HOOK_FUNC(ULONG, promotionCallback, struct Hook *hook,
  1121.                      Object *obj,
  1122.                      va_list args)
  1123.  
  1124. { XBoardClassData *data = INST_DATA(ThisClass, obj);
  1125.   int c;
  1126.   LONG fromX, fromY, toX, toY;
  1127.  
  1128.   c = va_arg(args, int);
  1129.  
  1130.   fromX = data->fromX;
  1131.   fromY = data->fromY;
  1132.   toX = data->toX;
  1133.   toY = data->toY;
  1134.  
  1135.   set(_win(obj), MUIA_Window_Sleep, FALSE);
  1136.  
  1137.   if (fromX >= 0  &&  fromX <=7   &&  fromY >= 0  &&  fromY <= 7  &&
  1138.       toX >= 0    &&  toX   <= 7  &&  toY >= 0    &&  toY <= 7    &&
  1139.       c != NULLCHAR)
  1140.   { UserMoveEvent(fromX, fromY, toX, toY, c);
  1141.   }
  1142.   PromotionPopDown(ThisClass, obj);
  1143.   return(0);
  1144. }
  1145.  
  1146. struct Hook promotionCallbackHook =
  1147. { { NULL, NULL },
  1148.   (HOOKFUNC) promotionCallback,
  1149.   NULL,
  1150.   NULL
  1151. };
  1152.  
  1153. VOID PromotionPopUp(Class *cl, Object *obj)
  1154.  
  1155. { XBoardClassData *data = INST_DATA(cl, obj);
  1156.   APTR win, queenButton, knightButton, rookButton, bishopButton;
  1157.   APTR app = _app(obj);
  1158.   ULONG open;
  1159.  
  1160.   if (data->promotionUp)
  1161.   { return;
  1162.   }
  1163.  
  1164.   win = WindowObject,
  1165.         MUIA_Window_ID, MAKE_ID('P','R','O','M'),
  1166.         MUIA_Window_Title, "Promotion requester",
  1167.         WindowContents, VGroup,
  1168.         Child, TextObject,
  1169.             MUIA_Text_Contents, "Promote piece to what?",
  1170.         End,
  1171.         Child, ColGroup(2),
  1172.             Child, queenButton = KeyButton("Queen", 'q'),
  1173.             Child, rookButton = KeyButton("Rook", 'r'),
  1174.             Child, bishopButton = KeyButton("Bishop", 'b'),
  1175.             Child, knightButton = KeyButton("Knight", 'k'),
  1176.         End,
  1177.         End,
  1178.     End;
  1179.  
  1180.   if (!win)
  1181.   { return;
  1182.   }
  1183.   DoMethod(app, OM_ADDMEMBER, win);
  1184.   set(win, MUIA_Window_Open, TRUE);
  1185.   get(win, MUIA_Window_Open, &open);
  1186.   if (!open)
  1187.   { DoMethod(app, OM_REMMEMBER, win);
  1188.     MUI_DisposeObject(win);
  1189.     return;
  1190.   }
  1191.  
  1192.   data->promotionUp = win;
  1193.  
  1194.   DoMethod(win, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
  1195.        obj, 3, MUIM_CallHook, &promotionCallbackHook, (int) '\0');
  1196.   DoMethod(queenButton, MUIM_Notify, MUIA_Pressed, FALSE,
  1197.        obj, 3, MUIM_CallHook, &promotionCallbackHook, (int) 'q');
  1198.   DoMethod(rookButton, MUIM_Notify, MUIA_Pressed, FALSE,
  1199.        obj, 3, MUIM_CallHook, &promotionCallbackHook, (int) 'r');
  1200.   DoMethod(bishopButton, MUIM_Notify, MUIA_Pressed, FALSE,
  1201.        obj, 3, MUIM_CallHook, &promotionCallbackHook, (int) 'b');
  1202.   DoMethod(knightButton, MUIM_Notify, MUIA_Pressed, FALSE,
  1203.        obj, 3, MUIM_CallHook, &promotionCallbackHook, (int) 'n');
  1204.   set(_win(obj), MUIA_Window_Sleep, TRUE);
  1205. }
  1206. /**/
  1207.  
  1208.  
  1209. /*** MUIM_HandleInput method
  1210. **/
  1211. ULONG xboardmHandleInput(Class *cl, Object *obj, struct MUIP_HandleInput *msg)
  1212.  
  1213. { XBoardClassData *data = INST_DATA(cl, obj);
  1214.  
  1215.   if (msg->imsg)
  1216.   { LONG x, y;
  1217.     ULONG left = ((_width(obj) - (data->squareWidth << 3)) >> 2) + _mleft(obj);
  1218.     ULONG top = ((_height(obj) - (data->squareHeight << 3)) >> 2) + _mtop(obj);
  1219.  
  1220.     x = 7 - (msg->imsg->MouseX - left) / data->squareWidth;
  1221.     y = (msg->imsg->MouseY - top) / data->squareHeight;
  1222.  
  1223.     if (!data->flipView)
  1224.     { y = BOARD_SIZE - 1 - y;
  1225.       x = BOARD_SIZE - 1 - x;
  1226.     }
  1227.  
  1228.     if (x < 0  ||  x >= BOARD_SIZE  ||  y < 0  ||  y >= BOARD_SIZE)
  1229.     { x = -2;
  1230.       y = -2;
  1231.     }
  1232.  
  1233.     switch(msg->imsg->Class)
  1234.     { case IDCMP_MOUSEBUTTONS:
  1235.     if (data->promotionUp)
  1236.     { PromotionPopDown(cl, obj);
  1237.     }
  1238.  
  1239.     if (msg->imsg->Code == SELECTDOWN)
  1240.     { if ((msg->imsg->Qualifier &
  1241.            (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_CAPSLOCK))
  1242.           ||  !OKToStartUserMove(x, y))
  1243.       { data->fromX = -1;
  1244.         data->fromY = -1;
  1245.       }
  1246.       else
  1247.       { data->fromX = x;
  1248.         data->fromY = y;
  1249.       }
  1250.     }
  1251.     else if (msg->imsg->Code == SELECTUP)
  1252.     { if (msg->imsg->Qualifier &
  1253.           (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_CAPSLOCK))
  1254.       { if (data->editPosition
  1255.         &&  x >= 0  &&  x < BOARD_SIZE
  1256.         &&  y >= 0  &&  y < BOARD_SIZE)
  1257.         { data->fromX = x;
  1258.           data->fromY = y;
  1259.           PiecePopUp(cl, obj);
  1260.         }
  1261.       }
  1262.       else
  1263.       { if (IsPromotion(data->fromX, data->fromY, x, y))
  1264.         { if (data->alwaysPromoteToQueen)
  1265.           { UserMoveEvent(data->fromX, data->fromY, x, y, 'q');
  1266.         data->fromX = -1;
  1267.         data->fromY = -1;
  1268.           }
  1269.           else
  1270.           { data->toX = x;
  1271.         data->toY = y;
  1272.         PromotionPopUp(cl, obj);
  1273.           }
  1274.         }
  1275.         else
  1276.         { UserMoveEvent(data->fromX, data->fromY, x, y, NULLCHAR);
  1277.         }
  1278.       }
  1279.     }
  1280.     break;
  1281.     }
  1282.   }
  1283.   return(0);
  1284. }
  1285. /**/
  1286.  
  1287.  
  1288. /*** MUIM_Setup method
  1289. **/
  1290. ULONG xboardmSetup(Class *cl, Object *obj, struct MUIP_Setup *msg)
  1291.  
  1292. { XBoardClassData *data = INST_DATA(cl, obj);
  1293.   ULONG result;
  1294.  
  1295.   if ((result = DoSuperMethodA(cl, obj, (Msg) msg)))
  1296.   { MUI_RequestIDCMP(obj, IDCMP_MOUSEBUTTONS);
  1297.  
  1298.     if ((data->lightSquarePen = data->reqLightSquarePen) == -1)
  1299.     { data->lightSquarePen = muiRenderInfo(obj)->mri_Pens[MPEN_HALFSHINE];
  1300.     }
  1301.     if ((data->darkSquarePen = data->reqDarkSquarePen) == -1)
  1302.     { data->darkSquarePen = muiRenderInfo(obj)->mri_Pens[MPEN_HALFSHADOW];
  1303.     }
  1304.     if ((data->whitePiecePen = data->reqWhitePiecePen) == -1)
  1305.     { data->whitePiecePen = muiRenderInfo(obj)->mri_Pens[MPEN_SHINE];
  1306.     }
  1307.     if ((data->blackPiecePen = data->reqBlackPiecePen) == -1)
  1308.     { data->blackPiecePen = muiRenderInfo(obj)->mri_Pens[MPEN_SHADOW];
  1309.     }
  1310.   }
  1311.   return(result);
  1312. }
  1313. /**/
  1314.  
  1315.  
  1316. /*** MUIM_Cleanup method
  1317. **/
  1318. ULONG xboardmCleanup(Class *cl, Object *obj, Msg msg)
  1319.  
  1320. { MUI_RejectIDCMP(obj, IDCMP_MOUSEBUTTONS);
  1321.   return(DoSuperMethodA(cl, obj, msg));
  1322. }
  1323. /**/
  1324.  
  1325.  
  1326. /****** XBoard.mcc/MUIM_XBoard_DrawPosition ********************************
  1327. *
  1328. *   NAME
  1329. *       MUIM_XBoard_DrawPosition - draw a position
  1330. *
  1331. *   SYNOPSIS
  1332. *       (VOID) DoMethod(Object *XBoardObj, MUIM_XBoard_DrawPosition,
  1333. *                       ULONG fullRedraw, Board *board);
  1334. *
  1335. *   FUNCTION
  1336. *       This method redraws the chessboard and sets up a certain
  1337. *       position.
  1338. *
  1339. *   INPUTS
  1340. *       fullRedraw - if this is FALSE, the gadget will redraw only
  1341. *           those parts of the chessboard which have changed since
  1342. *           the last position
  1343. *       board - the position to display; NULL is a valid argument
  1344. *           and means to display the last position again
  1345. *
  1346. ***************************************************************************/
  1347. ULONG xboardmDrawPosition(Class *cl, Object *obj, Msg msg)
  1348.  
  1349. { XBoardClassData *data = INST_DATA(cl, obj);
  1350.   int fullRedraw;
  1351.   Board *board;
  1352.   va_list args = (va_list) msg;
  1353.  
  1354.   (void) va_arg(args, ULONG);
  1355.   fullRedraw = va_arg(args, int);
  1356.   board = va_arg(args, Board *);
  1357.  
  1358.   if (board)
  1359.   { CopyMem(board, data->currentBoard, sizeof(*board));
  1360.   }
  1361.   MUI_Redraw(obj, fullRedraw ? MADF_DRAWOBJECT : MADF_DRAWUPDATE);
  1362.   return(TRUE);
  1363. }
  1364. /**/
  1365.  
  1366.  
  1367. /*** MuiClassInit() function
  1368. **/
  1369. VOID MuiClassInit(VOID)
  1370.  
  1371. { if ((MUIMasterBase = OpenLibrary((STRPTR) "muimaster.library", 8)))
  1372.   { if ((SuperClass = MUI_GetClass(MUIC_Area)))
  1373.     { if ((ThisClass = MakeClass(NULL, NULL, SuperClass,
  1374.                  sizeof(XBoardClassData), 0)))
  1375.       { ThisClass->cl_Dispatcher.h_Entry = (HOOKFUNC) XBoardClassDispatcher;
  1376.     ThisClass->cl_Dispatcher.h_SubEntry = NULL;
  1377.     ThisClass->cl_Dispatcher.h_Data = NULL;
  1378.  
  1379.     InitBuiltinBitmaps();
  1380.     return;
  1381.       }
  1382.     }
  1383.   }
  1384.   exit(10);
  1385. }
  1386. /**/
  1387.  
  1388.  
  1389. /*** MuiClassClose() function
  1390. **/
  1391. VOID MuiClassClose(VOID)
  1392.  
  1393. { if (ThisClass)
  1394.   { FreeClass((Class *) ThisClass);
  1395.   }
  1396.   if (SuperClass)
  1397.   { MUI_FreeClass(SuperClass);
  1398.   }
  1399.   if (MUIMasterBase)
  1400.   { CloseLibrary(MUIMasterBase);
  1401.   }
  1402. }
  1403. /**/
  1404.  
  1405.  
  1406. /*** XBoardObject() function
  1407. **/
  1408. APTR XBoardObject(Tag firsttag, ...)
  1409.  
  1410. { return(NewObjectA(ThisClass, NULL, (struct TagItem *) &firsttag));
  1411. }
  1412. /**/
  1413.